package com.matt.service.care.impl;

import com.matt.commons.exception.BusinessException;
import com.matt.domain.Children;
import com.matt.domain.care.*;
import com.matt.foundation.model.DailyRange;
import com.matt.foundation.model.ErrorCode;
import com.matt.repository.care.HLDailyRecordRepository;
import com.matt.service.WxPushService;
import com.matt.service.care.HLDailyRecordService;
import com.matt.service.care.po.HLDailyRecordPO;
import com.tuo51.foudation.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class HLDailyRecordServiceImpl extends HLCareBaseServiceImpl<HLDailyRecord, HLDailyRecordRepository, HLDailyRecordPO> implements HLDailyRecordService {

    @Autowired
    private HLDailyRecordRepository baseRepository;

    @Autowired
    private WxPushService pushService;

    @Autowired
    @Override
    public void setBaseRepository(HLDailyRecordRepository repository){
        super.setBaseRepository(repository);
    }
    int rankOf(HLMedicationRecord record){
        int rank = 5;

        if (record.getReaction() == 3){
            rank = 2;
        }else if(record.getReaction() == 0){
            rank -= 1;
        }

        return rank;
    }

    int rankOf(HLPottyRecord record){
        int rank = 5;

        if (record.getMonkeyAss()){
            rank --;
        }

        if (record.getDiarrhea()){
            rank --;
        }

        if (record.getUncomfortable()){
            rank --;
        }

        if (record.getConstipation()){
            rank --;
        }

        return rank;
    }


    private HLDailyRecord attachRecord(HLDailyRecord dailyRecord, HLCareBaseRecord record){
        if (record.getClass() == HLSleepRecord.class){
            dailyRecord.setSleepCount( dailyRecord.getSleepCount() + 1);
            dailyRecord.setSleepStatusVal(((HLSleepRecord)record).getRankVal());
            dailyRecord.setSleepStatus(((HLSleepRecord) record).getDuration());
        }else if (record.getClass() == HLFeedingRecord.class){
            dailyRecord.setFeedingCount(dailyRecord.getFeedingCount() + 1);
            dailyRecord.setFeedingStatusVal(((HLFeedingRecord)record).getRankVal());
            dailyRecord.setFeedingStatus(((HLFeedingRecord) record).getFood());
        }else if (record.getClass() == HLMedicationRecord.class){
            dailyRecord.setMedicationCount(dailyRecord.getMedicationCount() + 1);
            dailyRecord.setMedicationStatusVal(rankOf((HLMedicationRecord)record));
            dailyRecord.setMedicationStatus(((HLMedicationRecord) record).getDrugName());
        }else if (record.getClass() == HLPottyRecord.class){
            dailyRecord.setPottyCount(dailyRecord.getPottyCount() + 1);
            dailyRecord.setPottyStatusVal(rankOf((HLPottyRecord) record));
            dailyRecord.setPottyStatus(((HLPottyRecord) record).getTypeStr());
        }else if (record.getClass() == HLTemperatureRecord.class){
            dailyRecord.setTemperatureCount(dailyRecord.getTemperatureCount() + 1);
            dailyRecord.setTemperature(((HLTemperatureRecord) record).getTemperature());
            dailyRecord.setTemperatureBodyState(((HLTemperatureRecord) record).getBodyState());
            //TODO 需要一个活动记录
//       } else if (record.getClass() == HLFeedingRecord.class){
//
//        }else {
//            return null;
        }else if (record.getClass() == HLMoreRecord.class){
            if (((HLMoreRecord)record).getMoreType().equals(0)){
                dailyRecord.setNurseCount(dailyRecord.getNurseCount() + 1);
            }else {
                dailyRecord.setDefecationCount(dailyRecord.getDefecationCount() + 1);
            }

        }else {
            return null;
        }
        return dailyRecord;
    }

    private Integer rankOf(HLMoreRecord record) {
        int rank = 5;

        if (record.getMonkeyAss()){
            rank --;
        }

        if (record.getDiarrhea()){
            rank --;
        }

        if (record.getUncomfortable()){
            rank --;
        }

        if (record.getConstipation()){
            rank --;
        }

        return rank;
    }

    public HLDailyRecord markCareRecord(String staffId, HLCareBaseRecord record){

        String daily = DateUtil.convertStr(record.getEventTime());

        HLDailyRecord dailyRecord = baseRepository.findTop1ByChildIdAndDailyAndDeletedIsFalse(record.getChildId(), daily);

        if (dailyRecord == null){
            dailyRecord = new HLDailyRecord();
            dailyRecord.setChildId(record.getChildId());
            dailyRecord.setChildName(record.getChildName());
            dailyRecord.setDaily(daily);
            dailyRecord.setEventTime(new Date());
            dailyRecord.setCreatedBy(staffId);
            dailyRecord.setAreaId(record.getAreaId());
//            // 如果 record 是 feed 类型，设置 HLDailyRecord 的 ID
//            if (record instanceof HLFeedingRecord) {
//                dailyRecord.setId(((HLFeedingRecord) record).getId());
//            }
        }

        dailyRecord.setEventTime(new Date());
        dailyRecord = attachRecord(dailyRecord, record);

        if (dailyRecord != null){
            baseRepository.save(dailyRecord);
        }

        return dailyRecord;
    }

    public List<HLDailyRecord> markCareRecords(String staffId, List<HLCareBaseRecord> records){

        if (records == null || records.size() == 0){
            return null;
        }

        List<HLDailyRecord> batch = new ArrayList<>();

        for (HLCareBaseRecord record : records) {
            String daily = DateUtil.convertStr(record.getEventTime());

            HLDailyRecord dailyRecord = baseRepository.findTop1ByChildIdAndDailyAndDeletedIsFalse(record.getChildId(), daily);

            if (dailyRecord == null) {
                dailyRecord = new HLDailyRecord();
                dailyRecord.setDaily(daily);
                dailyRecord.setChildId(record.getChildId());
                dailyRecord.setChildName(record.getChildName());
                dailyRecord.setCreatedBy(staffId);
                dailyRecord.setEventTime(new Date());
                dailyRecord.setAreaId(record.getAreaId());
//                // 如果 record 是 feed 类型，设置 HLDailyRecord 的 ID
//                if (record instanceof HLFeedingRecord) {
//                    dailyRecord.setId(((HLFeedingRecord) record).getId());
//                }
            }

            dailyRecord = attachRecord(dailyRecord, record);

            if (dailyRecord != null) {
                batch.add(dailyRecord);
            }
        }
        if (batch.size() > 0){
            baseRepository.saveAll(batch);
        }

        return batch;
    }

    @Override
    public void pushCareRecords(String staffId, List<HLCareBaseRecord> records){
        for (HLCareBaseRecord record : records){
            pushCareRecord(staffId, record);
        }
    }

    @Override
    public void pushCareRecord(String staffId, HLCareBaseRecord record){
        if (record.getClass() == HLHandoverRecord.class) {
            pushService.pushMedicalHandoverRecord((HLHandoverRecord) record, record.getChildId());
        }else if (record.getClass() == HLSleepRecord.class){

        }else if (record.getClass() == HLFeedingRecord.class){
            pushService.pushDietRecord((HLFeedingRecord) record, record.getChildId());
        }else if (record.getClass() == HLMedicationRecord.class){

        }else if (record.getClass() == HLPottyRecord.class){
            pushService.pushDefecationRecord((HLPottyRecord) record, record.getChildId());
        }
    }

    @Override
    public List<HLDailyRecord> getAllByChildIdsAndDaily(String areaId, String staffId, String[] childIds, Date daily) {
        if (daily == null){
            throw new BusinessException(ErrorCode.PARAM_CAN_NOT_BLANK, "参数错误");
        }

        //检查宝贝 权限
        List<Children> cs = childrenService.getByIds(childIds, areaId);

        return getAllByChildIdsAndDaily(areaId, staffId, cs, daily);
    }


    public List<HLDailyRecord> getAllByChildIdsAndDaily(String areaId, String staffId, List<Children> cs, Date daily){
        if (daily == null){
            throw new BusinessException(ErrorCode.PARAM_CAN_NOT_BLANK, "参数错误");
        }

        //检查宝贝 权限
        String[] childIds = cs.stream().map(o->o.getId()).toArray(String[]::new);

//        List<Children> cs = childrenService.getByIds(childIds, areaId);

        Map<String, Children> cache = cs.stream().collect(Collectors.toMap(Children::getId, o -> o));

        if (cs == null || cs.size() == 0 || childIds == null || cs.size() != childIds.length){
            throw new BusinessException(ErrorCode.SUCCESSFUL, "宝宝没找到");
        }

        //
        DailyRange dr = DailyRange.of(daily);

        Specification<HLDailyRecord> specification = new Specification<HLDailyRecord>() {
            @Override
            public Predicate toPredicate(Root<HLDailyRecord> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();

                CriteriaBuilder.In<Object> p4 = criteriaBuilder.in(root.get("childId"));
                for (String id : childIds){
                    p4.value(id);
                }

                Predicate p3 = criteriaBuilder.equal(root.get("deleted"), 0);
                Predicate p2 = criteriaBuilder.between(root.get("eventTime"), dr.getDayBegin(), dr.getDayEnd());
                Predicate p1 = criteriaBuilder.and(p2, p3, p4);

                query.where(p1);

                return query.getRestriction();
            }
        };

        List<HLDailyRecord> dailyRecords = baseRepository.findAll(specification);

//        dailyRecords.stream().forEach(o->{
//            o.setImgUrl(cache.get(o.getId()).getImgUrl());
//            o.setBirthday(cache.get(o.getId()).getBirthday());
//        });

        return dailyRecords;
    }

    public HLDailyRecord grantDailyRecord(String areaId, String staffId, HLDailyRecord record){
        return null;
    }

}
